
#include <vtkVersion.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkMath.h>
#include <vtkPolyDataReader.h>
#include <vtkSmoothPolyDataFilter.h>
#include "vtkScalarBarActor.h"
#include <vtkLookupTable.h>
#include <vtkFloatArray.h>
#include <vtkDoubleArray.h>
#include <vtkPointData.h>
#include <vtkLookupTable.h>


#define VTK_CREATE(type, var) \
  vtkSmartPointer<type> var = vtkSmartPointer<type>::New()

#define USAGE "Usage: Show 1 2 3 4\n"\
			  "where\n"\
			  "\t1. DataFile - VTK DataFile to be visualized \n"\
			  "\t2. width - specify the window width in pixels \n"\
			  "\t3. height - specify the window height in pixels \n"\
			  "\t4. Curvature/Thickness - Optional: show colormap of curvature or thickness \n"


// ./Show  midMyocardiumThickness.vtk 512 512 Thickness

void AttributeAdjustment(vtkPolyData* inputPolyData)
{

	int nTuples = vtkDoubleArray::SafeDownCast(	inputPolyData->GetPointData()->GetScalars() )->GetNumberOfTuples();
	std::cout << "nTuples: " << nTuples << std::endl;
	double* scalars = new double[nTuples];
	double mScalars = 0;
	for (int i = 0; i < nTuples; i++) // Calculate:  mean(x(:))
	{
		scalars[i] = vtkDoubleArray::SafeDownCast( inputPolyData->GetPointData()->GetScalars() )->GetValue(i);
		mScalars += scalars[i];
//std::cout << "scalars[i]: " << scalars[i] << std::endl;
	}
	mScalars /= nTuples;
	std::cout << "1--mScalars: " << mScalars << std::endl;

	for (int i = 0; i < nTuples; i++) // Update:  x = x-mean(x(:));
	{
		scalars[i] = scalars[i] - mScalars;
	}

	mScalars = 0;
	for (int i = 0; i < nTuples; i++) //ReCalculate:  mean(x(:))
	{
		mScalars += scalars[i];
	}
	mScalars /= nTuples;
	std::cout << "2--mScalars: " << mScalars << std::endl;

	double madScalars = 0;
	for (int i = 0; i < nTuples; i++) // Calculate:  mad(X(:)) = MEAN(ABS(X-MEAN(X))
	{
		madScalars += fabs(scalars[i] - mScalars);
	}
	madScalars /= nTuples;
	std::cout << "madScalars: " << madScalars << std::endl;

	for (int i = 0; i < nTuples; i++) // Update:  x = x/(2*mad(x(:)));
	{
//		scalars[i] = scalars[i] / (2 * madScalars);
//		if (scalars[i] > 2)
//			scalars[i] = 2;
//		if (scalars[i] < -2)
//			scalars[i] = -2;
		scalars[i] = scalars[i] / (2 * madScalars);
		if (scalars[i] > 1)
			scalars[i] = 1;
		if (scalars[i] < -1)
			scalars[i] = -1;
//		if (scalars[i] < 0)
//			scalars[i] = -scalars[i];
	}

	for (int i = 0; i < nTuples; i++) // Calculate:  mean(x(:))
	{
		vtkDoubleArray::SafeDownCast( inputPolyData->GetPointData()->GetScalars() )->SetValue(i,scalars[i]);
	}

}


int main(int argc, char *argv[])
{

	vtkPolyDataReader *reader1 = vtkPolyDataReader::New();
	reader1->SetFileName(argv[1]);
	reader1->Update();

	int width, height;
	width = atoi(argv[2]);
	height = atoi(argv[3]);

	std::string colorMap;
	bool showColorMap = false;
	std::cout << "argc is "<< argc << std::endl;
	if (argc > 4) { // Check the value of argc. If not enough parameters have been passed, inform user and exit.
		showColorMap = true;
		colorMap = argv[4];
		std::cout << "colorMap is "<< colorMap << std::endl;

	}

	 // Load Object
	vtkSmartPointer < vtkPolyData > inputPolyData1 = reader1->GetOutput();
	AttributeAdjustment(inputPolyData1);


	// Create input mapper
	vtkSmartPointer < vtkPolyDataMapper > inputMapper1 = vtkSmartPointer< vtkPolyDataMapper > ::New();
#if VTK_MAJOR_VERSION <= 5
  inputMapper1->SetInput(inputPolyData1);
#else
  inputMapper1->SetInputData(inputPolyData1);
#endif


	// Create input actor
	vtkSmartPointer < vtkActor > inputActor1 = vtkSmartPointer < vtkActor > ::New();
	inputActor1->SetMapper(inputMapper1);


	// Create renderers
	vtkSmartPointer < vtkRenderer > renderer1 = vtkSmartPointer < vtkRenderer> ::New();
	renderer1->AddActor(inputActor1);


	//Add renderer to renderwindow and render
	vtkSmartPointer < vtkRenderWindow > renderWindow = vtkSmartPointer< vtkRenderWindow > ::New();
	renderWindow->AddRenderer(renderer1);


	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	//Render and interact
	renderWindow->SetSize(width, height);

	if(showColorMap)
		renderWindow->SetWindowName(colorMap.c_str()); // Set the title

	renderWindow->Render();
	renderWindowInteractor->Start();



	return EXIT_SUCCESS;
}
